home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / wnos / wn941101 / domsubr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-02  |  38.2 KB  |  1,536 lines

  1. #include <ctype.h>
  2.  
  3. #include "config.h"
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "domain.h"
  7. #include "netuser.h"
  8. #include "socket.h"
  9. #include "files.h"
  10.  
  11. static struct rr *Rrlist[NRLIST];
  12.  
  13. #ifdef ENH
  14. struct dlist *Lorigin = NULLDLIST;
  15. struct rr *Rrlistl[NRLIST];
  16. char *Dorigin = NULLCHAR;
  17. #else
  18. static struct dlist *Lorigin = NULLDLIST;
  19. static struct rr *Rrlistl[NRLIST];
  20. static char *Dorigin = NULLCHAR;
  21. #endif
  22.  
  23. /*
  24. static int near
  25. strxlen(char *s)
  26. {
  27.     int i = 0;
  28.  
  29.     while(*s++ != '\0')
  30.         i++;
  31.     return i;
  32. }
  33. */
  34.  
  35. int
  36. sendquery(address,buf,len,bp,timeout)
  37. int32 address;
  38. char *buf;
  39. int len;
  40. struct mbuf **bp;
  41. int32 timeout;
  42. {
  43.     int s, resp = -1;
  44.     struct sockaddr_in server;
  45.  
  46.     if((s = socket(AF_INET,SOCK_DGRAM,0)) != -1) {
  47.         *bp = qdata(buf,(int16)len);
  48.         xfree(buf);
  49.         server.sin_family = AF_INET;
  50.         server.sin_port = IPPORT_DOMAIN;
  51.         server.sin_addr.s_addr = address;
  52.         send_mbuf(s,*bp,0,(char *)&server,sizeof(server));
  53.         if(timeout) {                   /* Wait for something to happen */
  54.             alarm(timeout);
  55.             resp = recv_mbuf(s,bp,0,NULLCHAR,0);
  56.             alarm(0L);
  57.         }
  58.         close_s(s);
  59.     }
  60.     return resp;
  61. }
  62.  
  63. static char * near
  64. dn_compress(char *cp,char *name)
  65. {
  66.     char *cp1;
  67.     int len, dlen = strlen(name);
  68.  
  69.     for(;;){
  70.         /* Look for next dot */
  71.         cp1 = strchr(name,'.');
  72.         len = (cp1 != NULLCHAR) ? (int)(cp1 - name) : dlen;
  73.         *cp++ = len;        /* Write length of component */
  74.         if(len == 0)
  75.             return cp;
  76.         /* Copy component up to (but not including) dot */
  77.         strncpy(cp,name,len);
  78.         cp += len;
  79.         if(cp1 == NULLCHAR){
  80.             *cp++ = 0;    /* Last one; write null and finish */
  81.             return cp;
  82.         }
  83.         name += len+1;
  84.         dlen -= len+1;
  85.     }
  86. }
  87.  
  88. /* Convert a compressed domain name to the human-readable form */
  89. static int near
  90. dn_expand(msg,eom,compressed,full,fullen)
  91. char *msg;                    /* Complete domain message */
  92. char *eom;
  93. char *compressed;            /* Pointer to compressed name */
  94. char *full;                    /* Pointer to result buffer */
  95. int fullen;                    /* Length of same */
  96. {
  97.     unsigned int slen;        /* Length of current segment */
  98.     int clen = 0;            /* Total length of compressed name */
  99.     int indirect = 0;        /* Set if indirection encountered */
  100.     int nseg = 0;            /* Total number of segments in name */
  101.     char *cp = compressed;
  102.  
  103.     for(;;){
  104.         slen = uchar(*cp++);    /* Length of this segment */
  105.         if(!indirect)
  106.             clen++;
  107.         if((slen & 0xc0) == 0xc0){
  108.             if(!indirect)
  109.                 clen++;
  110.             indirect = 1;
  111.             /* Follow indirection */
  112.             cp = &msg[((slen & 0x3f)<<8) + uchar(*cp)];
  113.             slen = uchar(*cp++);
  114.         }
  115.         if(slen == 0)    /* zero length == all done */
  116.             break;
  117.         fullen -= slen + 1;
  118.         if(fullen < 0)
  119.             return -1;
  120.         if(!indirect)
  121.             clen += slen;
  122.         while(slen-- != 0)
  123.             *full++ = *cp++;
  124.         *full++ = '.';
  125.         nseg++;
  126.     }
  127.     if(nseg == 0){
  128.         /* Root name; represent as single dot */
  129.         *full++ = '.';
  130.         fullen--;
  131.     }
  132.     *full++ = '\0';
  133.     fullen--;
  134.     return clen;    /* Length of compressed message */
  135. }
  136.  
  137. static char * near
  138. getq(qp,msg,cp)
  139. struct quest *qp;
  140. char *msg;
  141. char *cp;
  142. {
  143.     int len;
  144.     char name[512];
  145.  
  146.     if((len = dn_expand(msg,NULLCHAR,cp,name,sizeof(name))) == -1)
  147.         return NULLCHAR;
  148.     cp += len;
  149.     qp->qname = strxdup(name);
  150.     qp->qtype = get16(cp);
  151.     cp += 2;
  152.     qp->qclass = get16(cp);
  153.     cp += 2;
  154.     return cp;
  155. }
  156.  
  157. /* Read a resource record from a domain message into a host structure */
  158. static char * near
  159. ntohrr(rrp,msg,cp)
  160. struct rr *rrp;    /* Pointer to allocated resource record structure */
  161. char *msg;    /* Pointer to beginning of domain message */
  162. char *cp;    /* Pointer to start of encoded RR record */
  163. {
  164.     int len;
  165.     char name[512];
  166.  
  167.     if((len = dn_expand(msg,NULLCHAR,cp,name,sizeof(name))) == -1)
  168.         return NULLCHAR;
  169.     cp += len;
  170.     rrp->name = strxdup(name);
  171.     rrp->type = get16(cp);
  172.     cp += 2;
  173.     rrp->class = get16(cp);
  174.     cp+= 2;
  175.     rrp->ttl = get32(cp);
  176.     cp += 4;
  177.     rrp->rdlength = get16(cp);
  178.     cp += 2;
  179.     switch(rrp->type){
  180.     case TYPE_CNAME:
  181.     case TYPE_MB:
  182.     case TYPE_MG:
  183.     case TYPE_MR:
  184.     case TYPE_NS:
  185.     case TYPE_PTR:
  186.         /* These types all consist of a single domain name;
  187.          * convert it to ascii format
  188.          */
  189.         if((len = dn_expand(msg,NULLCHAR,cp,name,sizeof(name))) == -1)
  190.             return NULLCHAR;
  191.         rrp->rdata.name = strxdup(name);
  192.         cp += len;
  193.         break;
  194.     case TYPE_A:
  195.         /* Just read the address directly into the structure */
  196.         rrp->rdata.addr = get32(cp);
  197.         cp += 4;
  198.         break;
  199.     case TYPE_HINFO:
  200.         rrp->rdata.hinfo.cpu = (char *)mxallocw(*cp+1);
  201.             strncpy(rrp->rdata.hinfo.cpu,cp+1,*cp);
  202.         cp += *cp + 1;
  203.         rrp->rdata.hinfo.os = (char *)mxallocw(*cp+1);
  204.             strncpy(rrp->rdata.hinfo.os,cp+1,*cp);
  205.         cp += *cp + 1;
  206.         break;
  207.     case TYPE_MX:
  208.         rrp->rdata.mx.pref = get16(cp);
  209.         cp += 2;
  210.         /* Get domain name of exchanger */
  211.         if((len = dn_expand(msg,NULLCHAR,cp,name,sizeof(name))) == -1) {
  212.             xfree(rrp->name);
  213.             return NULLCHAR;
  214.         }
  215.         rrp->rdata.mx.exch = strxdup(name);
  216.         cp += len;
  217.         break;
  218.     case TYPE_SOA:
  219.         /* Get domain name of name server */
  220.         if((len = dn_expand(msg,NULLCHAR,cp,name,sizeof(name))) == -1) {
  221.             xfree(rrp->name);
  222.             return NULLCHAR;
  223.         }
  224.         rrp->rdata.soa = (struct soa *)mxallocw(sizeof(struct soa));
  225.         rrp->rdata.soa->mname = strxdup(name);
  226.         cp += len;
  227.  
  228.         /* Get domain name of responsible person */
  229.         if((len = dn_expand(msg,NULLCHAR,cp,name,sizeof(name))) == -1) {
  230.             xfree(rrp->rdata.soa->mname);
  231.             xfree(rrp->rdata.soa);
  232.             xfree(rrp->name);
  233.             return NULLCHAR;
  234.         }
  235.         rrp->rdata.soa->rname = strxdup(name);
  236.         cp += len;
  237.  
  238.         rrp->rdata.soa->serial = get32(cp);
  239.         cp += 4;
  240.         rrp->rdata.soa->refresh = get32(cp);
  241.         cp += 4;
  242.         rrp->rdata.soa->retry = get32(cp);
  243.         cp += 4;
  244.         rrp->rdata.soa->expire = get32(cp);
  245.         cp += 4;
  246.         rrp->rdata.soa->minimum = get32(cp);
  247.         cp += 4;
  248.         break;
  249.     case TYPE_TXT:
  250.         /* Just stash */
  251.         rrp->rdata.data = mxallocw(rrp->rdlength);
  252.         memcpy(rrp->rdata.data,cp,rrp->rdlength);
  253.         cp += rrp->rdlength;
  254.         break;
  255.     case TYPE_MD:    /* Not supported */
  256.     case TYPE_MF:    /* Not supported */
  257.     case TYPE_NULL: /* Not supported */
  258.     case TYPE_WKS:    /* Not supported */
  259.     case TYPE_MINFO:    /* Not supported */
  260.         if((len = dn_expand(msg,NULLCHAR,cp,name,sizeof(name))) == -1) {
  261.             xfree(rrp->name);
  262.             return NULLCHAR;
  263.         }
  264.         rrp->rdata.name = strxdup(name);
  265.         cp += len;
  266.         break;
  267.     default:
  268.         /* Ignore */
  269.         cp += rrp->rdlength;
  270.         break;
  271.     }
  272.     return cp;
  273. }
  274.  
  275. static char * near
  276. htonrr(rr,buffer)
  277. struct rr *rr;
  278. char *buffer;
  279. {
  280.     struct rr *rrp;
  281.     char *p;
  282.     int i, len;
  283.     char *cp = buffer;
  284.  
  285.     for(rrp = rr; rrp != NULLRR; rrp = rrp->next) {
  286.         i = strlen(rrp->name);
  287.         if(rrp->name[i-1] != '.' && rrp->origin != NULLCHAR) {
  288.             p = mxallocw(i + strlen(rrp->origin) + 2);
  289.             sprintf(p,"%s.%s",rrp->name,rrp->origin);
  290.             cp = dn_compress(cp,p);
  291.             xfree(p);
  292.         }
  293.         else
  294.             cp = dn_compress(cp,rrp->name);
  295.         cp = put16(cp,rrp->type);
  296.         cp = put16(cp,rrp->class);
  297.         cp = put32(cp,3600L);        /* time to live */
  298.         cp = put16(cp,rrp->rdlength);
  299.         switch(rrp->type) {
  300.         case TYPE_A:
  301.             cp = put32(cp,rrp->rdata.addr);
  302.             break;
  303.         case TYPE_SOA:
  304.             cp = dn_compress(cp,rrp->rdata.soa->mname);
  305.             cp = dn_compress(cp,rrp->rdata.soa->rname);
  306.             cp = put32(cp,rrp->rdata.soa->serial);
  307.             cp = put32(cp,rrp->rdata.soa->refresh);
  308.             cp = put32(cp,rrp->rdata.soa->retry);
  309.             cp = put32(cp,rrp->rdata.soa->expire);
  310.             cp = put32(cp,rrp->rdata.soa->minimum); 
  311.             break;
  312.         case TYPE_HINFO:
  313.             *cp++ = len = strlen(rrp->rdata.hinfo.cpu);
  314.             strncpy(cp,rrp->rdata.hinfo.cpu,len); 
  315.             cp += len;
  316.             *cp++ = len = strlen(rrp->rdata.hinfo.os);
  317.             strncpy(cp,rrp->rdata.hinfo.os,len); 
  318.             cp += len;
  319.             break;
  320.         case TYPE_MX:
  321.             cp = put16(cp,rrp->rdata.mx.pref);
  322.             cp = dn_compress(cp,rrp->rdata.mx.exch);
  323.             break;
  324.         case TYPE_CNAME:
  325.         case TYPE_MB:
  326.         case TYPE_MG:
  327.         case TYPE_MR:
  328.         case TYPE_NS:
  329.         case TYPE_PTR:
  330.             cp = dn_compress(cp,rrp->rdata.data);
  331.             break;
  332.         case TYPE_MINFO:    /* Unsupported type */
  333.         cp = dn_compress(cp,rrp->rdata.minfo.rmailbx);
  334.         cp = dn_compress(cp,rrp->rdata.minfo.emailbx);
  335.         case TYPE_MD:        /* Unsupported type */
  336.         case TYPE_MF:        /* Unsupported type */
  337.         case TYPE_NULL:        /* Unsupported type */
  338.         case TYPE_WKS:        /* Unsupported type */
  339.             cp = dn_compress(cp,rrp->rdata.data);
  340.             break;
  341.         case TYPE_TXT:
  342.         default:
  343.             cp = put16(cp,rrp->rdlength);
  344.             for(i=0 ; i < rrp->rdlength ; i++)
  345.                 *cp++ = rrp->rdata.data[i];
  346.             break;
  347.         }
  348.     }
  349.     return cp;
  350. }
  351.  
  352. /* analyse suffixes for names to be added to the memory list */
  353. /* if Lorigin is empty, PA0GRI's domain stuf is not active.  */
  354. static void near
  355. analsuf(rrp)
  356. struct rr *rrp;
  357. {
  358.     char *n1, *n2;
  359.     int i;
  360.     struct dlist *llist, *lorigin;
  361.  
  362.     if(rrp->origin != NULLCHAR)
  363.         return; /* no job for me. */
  364.     if((llist = Lorigin) != NULLDLIST) { /* Am i working for PA0GRI? */
  365.         i = strlen(rrp->name);
  366.         if(rrp->name[i-1] == '.') {
  367.             n1 = &rrp->name[i-1];
  368.             n2 = strchr(rrp->name,'.');
  369.             if(n1 == n2){
  370.                 return; /* only 1 dot */
  371.             }
  372.             n2++;   /* point byond dot */
  373.             while(llist != NULLDLIST) {
  374.                 lorigin = llist;
  375.                 if(strcmp(llist->name,n2) == 0)
  376.                     break;
  377.                 llist = llist->next;
  378.             }
  379.             if(llist == NULLDLIST) {
  380.                 llist = (struct dlist *)mxallocw(sizeof(struct dlist));
  381.                 llist->name = strxdup(n2);
  382.                 lorigin->next = llist;
  383.             }
  384.             rrp->origin = llist->name;
  385.             n2--;
  386.             *n2 = '\0'; /* dot to EOS */
  387.             n1 = strxdup(rrp->name);
  388.             xfree(rrp->name);
  389.             rrp->name = n1;
  390.         }
  391.     }
  392. }
  393.  
  394. /* test a rr against a given name and type. The name can be:
  395.  1 a fully qualified name    (EG: pa0gri.ampr.org.)
  396.     or (if not fully qualified)
  397.  2 a name without a dot and no origin and suffix
  398.  3 a name without a dot and an origin and no suffix
  399.  4 a name without a dot and an origin and a suffix
  400.  *
  401.  * return 0 if not comparable, case value if it is good
  402.  */
  403. static int near
  404. dfind_cmp(rrp,name,nlen,dlen)
  405. struct rr *rrp;
  406. char *name;
  407. int nlen;
  408. int dlen;
  409. {
  410.     int olen = 0, rlen = strlen(rrp->name);
  411.  
  412.     if(rrp->origin != NULLCHAR) {
  413.         olen = strlen(rrp->origin);
  414.         if(rrp->origin[olen - 1] == '.')
  415.             --olen;
  416.     }
  417.  
  418. /* 1st test: is the name equal to the fully qualified rrp name? (minus traling .) */
  419.     if(rrp->name[rlen - 1] == '.') {
  420.         --rlen;
  421.         if(rlen == nlen && strnicmp(name,rrp->name,rlen) == 0)
  422.             return 1;
  423.     }
  424.  
  425. /* second test: is the name equal to the rrp name */
  426.     if(Dsuffix == NULLCHAR && rrp->origin == NULLCHAR) {
  427.         if(nlen == rlen && strnicmp(name,rrp->name,rlen) == 0)
  428.             return 2;
  429.         if(nlen + 9 == rlen             /* special case for .ampr.org. */
  430.          && strnicmp(name,rrp->name,nlen) == 0
  431.          && strnicmp(&rrp->name[nlen+1],"ampr.org",8) == 0
  432.          && rrp->name[nlen] == '.')
  433.             return 3;
  434.     } else if(Dsuffix == NULLCHAR && rrp->origin != NULLCHAR) {
  435.         if(nlen == rlen && strnicmp(name,rrp->name,rlen) == 0)
  436. /* third test: name equal to rrp name (excluding origin) */
  437.             return 4;
  438.         else if((rlen + olen + 1) == nlen
  439.              && strnicmp(name,rrp->name,rlen) == 0
  440.              && name[rlen] == '.'
  441.              && strnicmp(&name[rlen + 1],rrp->origin,olen) == 0)
  442. /* fourth test: name equal rrp name + origin */
  443.                 return 5;
  444.     } else if(Dsuffix != NULLCHAR && rrp->origin != NULLCHAR) {
  445.         if(rlen == nlen && dlen == olen
  446.          && strnicmp(name,rrp->name,rlen) == 0
  447.          && strnicmp(Dsuffix,rrp->origin,dlen) == 0)
  448. /* fifth test: name equal to rrp name and origin equal to domain suffix */
  449.             return 6;
  450.         else if((rlen + olen + 1) == nlen
  451.              && strnicmp(name,rrp->name,rlen) == 0
  452.              && name[rlen] == '.'
  453.              && strnicmp(&name[rlen + 1],rrp->origin,olen) == 0)
  454. /* sixth test: name equal to rrp name + origin) */
  455.                 return 7;
  456.     } else if(Dsuffix != NULLCHAR && rrp->origin == NULLCHAR) {
  457.         if(rlen == nlen && strnicmp(name,rrp->name,rlen) == 0)
  458. /* seventh test: name equal to rrp name and no origin (ignore domain suffix) */
  459.             return 8;
  460.         else
  461.             if((nlen + dlen + 1) == rlen
  462.              && strnicmp(name,rrp->name,nlen) == 0
  463.              && rrp->name[nlen] == '.'
  464.              && strnicmp(&rrp->name[nlen + 1],Dsuffix,dlen) == 0)
  465. /* eight test: name plus suffix equal to rrp name ) */
  466.                 return 9;
  467.     }
  468.     return 0;
  469. }
  470.  
  471. /* Search local domain file for resource record of specified name and type.
  472.  * If records were found, the domain file pointer is left just after the last
  473.  * one. If not, the file is rewound.
  474.  */
  475. static struct rr * near
  476. dfindf(dbase,name,type,memory)
  477. FILE *dbase;
  478. char *name;
  479. int type;
  480. struct rr_memory *memory;
  481. {
  482.     struct rr *rrp;
  483.     int nlen, dlen;
  484.  
  485.     if(DBloaded)
  486.         return NULLRR;
  487.  
  488.     nlen = strlen(name);
  489.     if(name[nlen - 1] == '.') /* forget trailing . for tests. */
  490.         --nlen;
  491.  
  492.     dlen = (Dsuffix != NULLCHAR) ? (strlen(Dsuffix) - 1) : 0;
  493.     /* Search file */
  494.     while((rrp = get_rr(dbase,memory)) != NULLRR){
  495.         if(rrp->class == CLASS_IN)
  496.             if(type == rrp->type || type == TYPE_ANY)
  497.                 if(dfind_cmp(rrp,name,nlen,dlen) != 0)
  498.                     break;
  499.         free_rr(rrp);
  500.         pwait(NULL);    /* Give up CPU for a while, this takes time */
  501.     }
  502.     if(rrp == NULLRR)
  503.         rewind(dbase);
  504.     return rrp;
  505. }
  506. #ifdef forgetme
  507.         /* If the first character is a '*' it is replaced by the
  508.            first part of the sought domain. */
  509. /* forget about this till other areas know what to do with multiple rr's.
  510.         if(*rrp->name == '*'){
  511.             if(rrp->name[rlen-1] == '.')
  512.                 p = mxallocw(rlen);
  513.             else
  514.                 p = mxallocw(rlen + olen);
  515.             strcpy(p,rrp->name+2);
  516.             if(rrp->name[rlen-1] != '.' && rrp->origin != NULLCHAR)
  517.                 strcat(p,rrp->origin);
  518.             rrp->origin = p;
  519.             olen = strlen(rrp->origin);
  520.             if(rrp->origin[olen-1] == '.')
  521.                 --olen;
  522.             xfree(rrp->name);
  523.             rrp->name = (char *)mxallocw(nlen + 1);
  524.             if(nlen > olen
  525.              && strnicmp(name+nlen-olen,rrp->origin, olen) == 0)
  526.                 strncpy(rrp->name,name,nlen-olen-1);
  527.             else {
  528.                 free_rr(rrp);
  529.                 continue;
  530.             }
  531.             rlen = strlen(rrp->name);
  532.         }
  533. end of skip code */
  534. #endif
  535.  
  536. struct rr *
  537. dfind(dbase,name,type,memory)
  538. FILE *dbase;
  539. char *name;
  540. int type;
  541. struct rr_memory *memory;
  542. {
  543.     struct rr *rrp, *rrl;
  544.     int nlen, dlen, i, rtype;
  545.     struct rr *rrsave = NULLRR;
  546.  
  547.     if(type >= NDTYPES)
  548.         if(type == TYPE_ANY) {
  549.             for(i = 0 ; (rtype = Dstypes[i]) != 0; ) {
  550.                 rrp = dfind(dbase,name,rtype,memory);
  551.                 if(rrp != NULLRR) {
  552.                     if(rrsave == NULLRR){
  553.                         rrsave = rrp;
  554.                         rrl = rrp;
  555.                     } else {
  556.                         rrl->next = rrp;
  557.                         rrl = rrl->next;
  558.                     }
  559.                 } else {
  560.                     i++;
  561.                     memory->rrp = NULLRR;
  562.                 }
  563.             }
  564.             if(rrsave != NULLRR)
  565.                 return rrsave;
  566.         } else {
  567.             goto filetest; /* to big a type for memory */
  568.         }
  569.     if((rrp = Rrlist[type]) != NULLRR) {
  570.         if(memory->rrp != NULLRR){
  571.             rrp = memory->rrp; /* go off where we left before ! */
  572.             rrp = rrp->next; /* but take the next */
  573.         }
  574.         nlen = strlen(name);
  575.         if(name[nlen - 1] == '.') /* forget trailing . for tests. */
  576.             --nlen;
  577.         dlen = (Dsuffix != NULLCHAR) ? (strlen(Dsuffix) - 1) : 0;
  578.  
  579.         /* Search core data beast */
  580.         while(rrp != NULLRR){
  581.             if(rrp->class == CLASS_IN)
  582.                 if(dfind_cmp(rrp,name,nlen,dlen) != 0)
  583.                         break;
  584.             rrp = rrp->next;
  585.         }
  586.         if(rrp != NULLRR){
  587.             rrl = copy_rr(rrp);
  588.             memory->rrp = rrp;
  589.             return rrl;
  590.         }
  591.         memory->rrp = NULLRR; /* end of list encountered */
  592.     } /* not found in memory, resort to file */
  593. filetest:
  594.     if(dbase != NULLFILE)
  595.         rrp = dfindf(dbase,name,type,memory);
  596.     return rrp;
  597. }
  598.  
  599. /* Add a record to the database only if it doesn't already exist */
  600. /* Return 1 if record is not added to memory list. This means the rr
  601.    can be freed. If 0 is returned the rr is added to the memory list */
  602. #ifndef ENH
  603. static
  604. #endif
  605. int
  606. add_rr(fp,rrp1)
  607. FILE *fp;
  608. struct rr *rrp1;
  609. {
  610.     int type, nlen;
  611.     char *name;
  612.     struct rr *rrp, *rr;
  613.     struct rr_memory *memory;
  614.  
  615.     analsuf(rrp1);
  616.     type = rrp1->type;
  617.     name = rrp1->name;
  618.     nlen = strlen(name);
  619.     memory = (struct rr_memory *)mxallocw(sizeof(struct rr_memory));
  620.     memory->rrp = NULLRR;
  621.     if(fp == NULLFILE) {
  622.         name = strxdup(rrp1->name);
  623.         while((rrp = dfind(fp,name,type,memory)) != NULLRR){
  624.             if(cmp_rr(rrp,rrp1) == 0){
  625.                 free_rr(rrp);
  626.                 xfree(memory->dorigin);
  627.                 xfree((char *)memory);
  628.                 xfree(name);
  629.                 return 1;
  630.             }
  631.             free_rr(rrp);
  632.         }
  633.         /* Not found in list, go add it */
  634.         xfree(memory->dorigin);
  635.         xfree((char *)memory);
  636.         xfree(name);
  637.         /* see if we have this kind of records. */
  638.         if((rr = Rrlist[type]) != NULLRR) {
  639.             rr = Rrlistl[type];
  640.             rr->next = rrp1;
  641.         } else  /* No, initialize first */
  642.             Rrlist[rrp1->type] = rrp1;
  643.         /* now set last */
  644.         Rrlistl[type] = rrp1;
  645.         return 0;
  646.     } else {
  647.         if(name[nlen - 1] != '.') {
  648.             if(rrp1->origin != NULLCHAR){
  649.                 name = (char *)mxallocw(nlen+strlen(rrp1->origin)+2);
  650.                 sprintf(name,"%s.%s",rrp1->name,rrp1->origin);
  651.             }
  652.         } else
  653.             name = strxdup(rrp1->name);
  654.         rewind(fp);
  655.         while((rrp = dfind(fp,name,type,memory)) != NULLRR){
  656.             if(cmp_rr(rrp,rrp1) == 0){
  657.                 free_rr(rrp);
  658.                 xfree(memory->dorigin);
  659.                 xfree((char *)memory);
  660.                 xfree(name);
  661.                 return 1;
  662.             }
  663.             free_rr(rrp);
  664.         }
  665.         xfree(memory->dorigin);
  666.         xfree((char *)memory);
  667.         xfree(name);
  668.         fseek(fp,0L,2);
  669.         put_rr(fp,rrp1,1);
  670.         return 1;
  671.     }
  672. }
  673.  
  674. /* Compare two resource records, returning 0 if equal, nonzero otherwise */
  675. static int
  676. cmp_rr(rr1,rr2)
  677. struct rr *rr1,*rr2;
  678. {
  679.     int i;
  680.  
  681.     if(rr1 == NULLRR || rr2 == NULLRR)
  682.         return -1;
  683.     if((i = strlen(rr1->name)) != strlen(rr2->name))
  684.         return 1;
  685.     if((i = strnicmp(rr1->name,rr2->name,i)) != 0)
  686.         return i;
  687.     if(rr1->type != rr2->type)
  688.         return 2;
  689.     if(rr1->class != rr2->class)
  690.         return 3;
  691.     if(rr1->rdlength == 0 && rr2->rdlength == 0)
  692.         return 0;
  693.     if(rr1->rdlength == 0 || rr2->rdlength == 0)
  694.         return 4;
  695.     /* Note: rdlengths are not compared because they vary depending
  696.      * on the representation (ASCII or encoded) this record was
  697.      * generated from.
  698.      */
  699.     switch(rr1->type){
  700.     case TYPE_A:
  701.         i = rr1->rdata.addr != rr2->rdata.addr;
  702.         break;
  703.     case TYPE_SOA:
  704.         i = rr1->rdata.soa->serial != rr2->rdata.soa->serial;
  705.         break;
  706.     case TYPE_HINFO:
  707.         i = strcmp(rr1->rdata.hinfo.cpu,rr2->rdata.hinfo.cpu) ||
  708.             strcmp(rr1->rdata.hinfo.os,rr2->rdata.hinfo.os);
  709.         break;
  710.     case TYPE_MX:
  711.         i = strcmp(rr1->rdata.mx.exch,rr2->rdata.mx.exch);
  712.         break;
  713.     case TYPE_MB:
  714.     case TYPE_MG:
  715.     case TYPE_MR:
  716.     case TYPE_PTR:
  717.     case TYPE_TXT:
  718.     case TYPE_NS:
  719.         i = strcmp(rr1->rdata.data,rr2->rdata.data);
  720.         break;
  721.     case TYPE_CNAME:
  722.         i = strcmp(rr1->rdata.data,rr2->rdata.data);
  723.         break;
  724.     case TYPE_MINFO:    /* Unsupported type */
  725.         i = strcmp(rr1->rdata.minfo.rmailbx,rr2->rdata.minfo.rmailbx) ||
  726.             strcmp(rr1->rdata.minfo.emailbx,rr2->rdata.minfo.emailbx);
  727.         break;
  728.     case TYPE_MD:        /* Unsupported type */
  729.     case TYPE_MF:        /* Unsupported type */
  730.     case TYPE_NULL:        /* Unsupported type */
  731.     case TYPE_WKS:        /* Unsupported type */
  732.         i = strcmp(rr1->rdata.data,rr2->rdata.data);
  733.         break;
  734.     }
  735.     return i;
  736. }
  737.  
  738. struct rr *
  739. copy_rr(rr)
  740. struct rr *rr;
  741. {
  742.     struct rr *rrp = (struct rr *)mxallocw(sizeof(struct rr));
  743.  
  744.     rrp->next = NULLRR;
  745.     rrp->soarec = rr->soarec;
  746.     rrp->name = strxdup(rr->name);
  747.     rrp->type = rr->type;
  748.     rrp->class = rr->class;
  749.     rrp->ttl = rr->ttl;
  750.     rrp->origin = rr->origin;
  751.     rrp->rdlength = rr->rdlength;
  752.     switch(rr->type){
  753.     case TYPE_A:
  754.         rrp->rdata.addr = rr->rdata.addr;
  755.         break;
  756.     case TYPE_CNAME:
  757.     case TYPE_MB:
  758.     case TYPE_MG:
  759.     case TYPE_MR:
  760.     case TYPE_NS:
  761.     case TYPE_PTR:
  762.     case TYPE_TXT:
  763.         rrp->rdata.name = strxdup(rr->rdata.name);
  764.         break;
  765.     case TYPE_HINFO:
  766.         rrp->rdata.hinfo.cpu = strxdup(rr->rdata.hinfo.cpu);
  767.         rrp->rdata.hinfo.os = strxdup(rr->rdata.hinfo.os);
  768.         break;
  769.     case TYPE_MX:
  770.         rrp->rdata.mx.pref = rr->rdata.mx.pref;
  771.         rrp->rdata.mx.exch = strxdup(rr->rdata.mx.exch);
  772.         break;
  773.     case TYPE_SOA:
  774.         rrp->rdata.soa = (struct soa *)mxallocw(sizeof(struct soa));
  775.         rrp->rdata.soa->mname = strxdup(rr->rdata.soa->mname);
  776.         rrp->rdata.soa->rname = strxdup(rr->rdata.soa->rname);
  777.         rrp->rdata.soa->serial = rr->rdata.soa->serial;
  778.         rrp->rdata.soa->refresh = rr->rdata.soa->refresh;
  779.         rrp->rdata.soa->retry = rr->rdata.soa->retry;
  780.         rrp->rdata.soa->expire = rr->rdata.soa->expire;
  781.         rrp->rdata.soa->minimum = rr->rdata.soa->minimum;
  782.         break;
  783.     case TYPE_MINFO:    /* Unsupported type */
  784.         rrp->rdata.minfo.rmailbx = strxdup(rr->rdata.minfo.rmailbx);
  785.         rrp->rdata.minfo.emailbx = strxdup(rr->rdata.minfo.emailbx);
  786.         break;
  787.     case TYPE_MD:        /* Unsupported type */
  788.     case TYPE_MF:        /* Unsupported type */
  789.     case TYPE_NULL:        /* Unsupported type */
  790.     case TYPE_WKS:        /* Unsupported type */
  791.         rrp->rdata.name = strxdup(rr->rdata.name);
  792.         break;
  793.     }
  794.     return rrp;
  795. }
  796.  
  797. #ifdef XXX
  798. struct rr *
  799. make_rr(source,dname,dclass,dtype,ttl,rdl,data)
  800. int source;
  801. char *dname;
  802. int16 dclass;
  803. int16 dtype;
  804. int32 ttl;
  805. int16 rdl;
  806. void *data;
  807. {
  808.     struct rr *newrr = (struct rr *)mxallocw(sizeof(struct rr));
  809.  
  810.     newrr->next = NULLRR;
  811.     newrr->soarec = NULLRR;
  812.     newrr->name = strxdup(dname);
  813.     newrr->class = dclass;
  814.     newrr->type = dtype;
  815.     newrr->ttl = ttl;
  816.     if((newrr->rdlength = rdl) == 0)
  817.         return newrr;
  818.  
  819.     if(dtype == TYPE_A) {
  820.         int32 *ap = (int32 *)data;
  821.         newrr->rdata.addr = *ap;
  822.     }
  823.     return copy_rr(newrr);
  824. }
  825. #endif
  826.  
  827. /* Free a chain of resource records */
  828. void
  829. free_rr(rrp)
  830. struct rr *rrp;
  831. {
  832.     struct rr *rr = rrp;
  833.  
  834.     while(rr != NULLRR) {
  835.         rrp = rr;
  836.         xfree(rrp->name);
  837.         if(rrp->rdlength != 0){
  838.             switch(rrp->type){
  839.             case TYPE_CNAME:
  840.             case TYPE_MB:
  841.             case TYPE_MG:
  842.             case TYPE_MR:
  843.             case TYPE_NS:
  844.             case TYPE_PTR:
  845.                 xfree(rrp->rdata.name);
  846.                 break;
  847.             case TYPE_A:
  848.                 break;    /* Nothing allocated in rdata section */
  849.             case TYPE_HINFO:
  850.                 xfree(rrp->rdata.hinfo.cpu);
  851.                 xfree(rrp->rdata.hinfo.os);
  852.                 break;
  853.             case TYPE_MX:
  854.                 xfree(rrp->rdata.mx.exch);
  855.                 break;
  856.             case TYPE_SOA:
  857.                 xfree(rrp->rdata.soa->mname);
  858.                 xfree(rrp->rdata.soa->rname);
  859.                 xfree((char *)rrp->rdata.soa);
  860.                 break;
  861.             case TYPE_TXT:
  862.                 xfree(rrp->rdata.data);
  863.                 break;
  864.             case TYPE_MD:        /* Unsupported type */
  865.             case TYPE_MF:        /* Unsupported type */
  866.             case TYPE_NULL:        /* Unsupported type */
  867.                 xfree(rrp->rdata.data);
  868.                 break;
  869.             case TYPE_WKS:        /* Unsupported type */
  870.                 break;
  871.             case TYPE_MINFO:    /* Unsupported type */
  872.                 xfree(rrp->rdata.minfo.rmailbx);
  873.                 xfree(rrp->rdata.minfo.emailbx);
  874.                 break;
  875.             }
  876.         }
  877.         rr = rrp->next;
  878.         xfree((char *)rrp);
  879.     }
  880. }
  881.  
  882. #ifndef ENH
  883. static
  884. #endif
  885. struct rr *
  886. get_rr(fp,memory)
  887. FILE *fp;
  888. struct rr_memory *memory;
  889. {
  890.     char line[256], contline[256];
  891.     struct rr *rrp;
  892.     struct dlist *lorigin,*ltemp;
  893.     char *name, *ttl, *class, *type, *data;
  894.     int i;
  895.     int32 value, atol();
  896.     char delim[] = " \t\r\n";
  897.  
  898.     if(fp == NULLFILE)
  899.         return NULLRR;
  900.  
  901.     /* Search file */
  902.     while(fgets(line,sizeof(line),fp),!feof(fp)){
  903.         if(*line == '#' || *line == ';')
  904.             continue;
  905.         if(*line == '$') {
  906.             data = strtok(line,delim);
  907.             if(strnicmp(data,"$origin",7) == 0) {
  908.                 data = strtok(NULLCHAR,delim);
  909.                 if(Db_initialize) {
  910.                     if(data != NULLCHAR) {
  911.                         ltemp = Lorigin;
  912.                         while(ltemp != NULLDLIST) {
  913.                             lorigin = ltemp;
  914.                             if(strcmp(ltemp->name,data) == 0)
  915.                                 break;
  916.                             ltemp = ltemp->next;
  917.                         }
  918.                         if(ltemp == NULLDLIST) {
  919.                             ltemp = (struct dlist *)mxallocw(sizeof(struct dlist));
  920.                             ltemp->name = strxdup(data);
  921.                             lorigin->next = ltemp;
  922.                             Dorigin = ltemp->name;
  923.                         } else {
  924.                             Dorigin = ltemp->name;
  925.                         }
  926.                     } else {
  927.                         Dorigin = NULLCHAR; /* empty origin */
  928.                     }
  929.                 }
  930.                 if(memory->dorigin != NULLCHAR)
  931.                     xfree(memory->dorigin);
  932.                 memory->dorigin = (data != NULLCHAR) ? strxdup(data) : NULLCHAR;
  933.             }
  934.             continue;
  935.         }
  936.         data = &line[0];    /* check for empty line */
  937.         while(*data)
  938.             if(!isspace(*data++)) {
  939.                 break;
  940.             }
  941.         /*
  942.          * now it is nor a # , ; or $ line
  943.          */
  944.         if(*data)
  945.             break;    /* there is something on it.. */
  946.     }
  947.  
  948.     if(feof(fp))
  949.         return NULLRR;
  950.  
  951.     rrp = (struct rr *)mxallocw(sizeof(struct rr));
  952.     if(isspace(line[0])) {    /* in case of previous name usage*/
  953.         name = "";
  954.         ttl = strtok(line,delim);
  955.     } else {
  956.         name = strtok(line,delim);
  957.         if(!strcmp(name,"@") && (memory->dorigin != NULLCHAR
  958.           || Dsuffix != NULLCHAR)){
  959.             name = (memory->dorigin != NULLCHAR) ? memory->dorigin : Dsuffix;
  960.         }
  961.         ttl = strtok(NULLCHAR,delim);
  962.     }
  963.     if(ttl == NULLCHAR)     /* If a line only contains a name */
  964.         goto badline;
  965.  
  966.     if((i = strlen(name)) == 0)
  967.         name = memory->Dname;
  968.     else
  969.         sprintf(memory->Dname,"%.125s",name);
  970.  
  971.     rrp->origin = (Dorigin != NULLCHAR) ? Dorigin : memory->dorigin;
  972.  
  973.     if(name[i-1] == '.')    /* if a fully qualified name comes along */
  974.         rrp->origin = NULLCHAR;    /* then it does not belong to an origin */
  975.     rrp->name = strxdup(name);
  976.  
  977.     if(!isdigit(ttl[0])){
  978.         /* Optional ttl field is missing; slide field over */
  979.         class = ttl;
  980.         ttl = NULLCHAR;
  981.         rrp->ttl = memory->Dttl;
  982.     } else {
  983.         memory->Dttl = atol(ttl);
  984.         rrp->ttl = memory->Dttl;
  985.         class = strtok(NULLCHAR,delim);
  986.     }
  987.  
  988.     if(class == NULLCHAR)     /* If a line only contains a name and ttl */
  989.         goto badline;
  990.  
  991.     if(strcmp(class,"IN") != 0){
  992.         /* Optional class field is missing; slide field over */
  993.         type = class;
  994.         class = NULLCHAR;
  995.         rrp->class = memory->Dclass;
  996.     } else {
  997.         memory->Dclass = CLASS_IN;
  998.         rrp->class = memory->Dclass;
  999.         type = strtok(NULLCHAR,delim);
  1000.     }
  1001.  
  1002.     if(type == NULLCHAR) {    /* If a class field is missing */
  1003. badline:
  1004.         tprintf("Error in domain file %s:\n-%s-\n",Dfile,line);
  1005.         free_rr(rrp);
  1006.         return NULLRR;
  1007.     }
  1008.  
  1009.     for(i = 0; i < NRLIST; i++) {
  1010.         if(strcmp(type,type2str(i)) == 0){
  1011.             rrp->type = i;
  1012.             break;
  1013.         }
  1014.     }
  1015.  
  1016.     data = strtok(NULLCHAR,delim);
  1017.  
  1018.     if(data == NULLCHAR)
  1019.         return rrp;
  1020.  
  1021.     switch(rrp->type){
  1022.     case TYPE_MD:        /* Unsupported yet */
  1023.     case TYPE_MF:        /* Unsupported yet */
  1024.     case TYPE_NULL:        /* Unsupported yet */
  1025.         rrp->rdlength = strlen(data) + 1;
  1026.         rrp->rdata.name = strxdup(data);
  1027.         break;
  1028.     case TYPE_WKS:        /* Unsupported yet */
  1029. /*
  1030.         rrp->wks = (struct wks *)mxallocw(sizeof(struct wks));
  1031.  */
  1032.         rrp->rdlength = strlen(data) + 1;
  1033.         rrp->rdata.name = strxdup(data);
  1034.         break;
  1035.     case TYPE_CNAME:
  1036.     case TYPE_MB:
  1037.     case TYPE_MG:
  1038.     case TYPE_MR:
  1039.     case TYPE_NS:
  1040.     case TYPE_PTR:
  1041.     case TYPE_TXT:
  1042.         rrp->rdlength = strlen(data) + 1;
  1043.         rrp->rdata.name = strxdup(data);
  1044.         break;
  1045.     case TYPE_A:
  1046.         rrp->rdlength = 4;
  1047.         rrp->rdata.addr = aton(data);
  1048.         break;
  1049.     case TYPE_HINFO:
  1050.         rrp->rdlength = strlen(data) + 2;
  1051.         rrp->rdata.hinfo.cpu = strxdup(data);
  1052.         if((data = strtok(NULLCHAR,delim)) != NULLCHAR){
  1053.             rrp->rdlength += strlen(data);
  1054.             rrp->rdata.hinfo.os = strxdup(data);
  1055.         }
  1056.         break;
  1057.     case TYPE_MINFO:
  1058.         rrp->rdlength = strlen(data) + 2;
  1059.         rrp->rdata.minfo.rmailbx = strxdup(data);
  1060.         if((data = strtok(NULLCHAR,delim)) != NULLCHAR){
  1061.             rrp->rdlength += strlen(data);
  1062.             rrp->rdata.minfo.emailbx = strxdup(data);
  1063.         }
  1064.         break;
  1065.     case TYPE_MX:
  1066.         rrp->rdata.mx.pref = (int16)atoi(data);
  1067.         rrp->rdlength = 2;
  1068.  
  1069.         /* Get domain name of exchanger */
  1070.         if((data = strtok(NULLCHAR,delim)) != NULLCHAR){
  1071.             rrp->rdlength += strlen(data) + 1;
  1072.             rrp->rdata.mx.exch = strxdup(data);
  1073.         }
  1074.         break;
  1075.     case TYPE_SOA:
  1076.         rrp->rdata.soa = (struct soa *)mxallocw(sizeof(struct soa));
  1077.         /* Get domain name of master name server */
  1078.         rrp->rdlength = strlen(data) + 1;
  1079.         rrp->rdata.soa->mname = strxdup(data);
  1080.  
  1081.         /* Get domain name of irresponsible person */
  1082.         if((data = strtok(NULLCHAR,delim)) != NULLCHAR){
  1083.             rrp->rdata.soa->rname = strxdup(data);
  1084.             rrp->rdlength += strlen(data) + 1;
  1085.         }
  1086.         data = strtok(NULLCHAR,delim);
  1087.         if(*data == '(') {    /* multiple line data */
  1088.             /* Search file */
  1089.             fgets(contline,256,fp);
  1090.             if(feof(fp))
  1091.                 break;
  1092.             data = strtok(contline,delim);
  1093.             for(i=0; i<5;i++) {
  1094.                 if(*data == ';' || data == NULLCHAR) {
  1095.                     fgets(contline,256,fp);
  1096.                     if(feof(fp)){
  1097.                             break;
  1098.                     }
  1099.                     data = strtok(contline,delim);
  1100.                 }
  1101.                 if(*data == ')')
  1102.                     break;
  1103.                 if(isdigit(*data)) {
  1104.                     value = atol(data);
  1105.                     switch (i) {
  1106.                     case 0:
  1107.                     rrp->rdata.soa->serial = value;
  1108.                         break;
  1109.                     case 1:
  1110.                     rrp->rdata.soa->refresh = value;
  1111.                         break;
  1112.                     case 2:
  1113.                     rrp->rdata.soa->retry = value;
  1114.                         break;
  1115.                     case 3:
  1116.                     rrp->rdata.soa->expire = value;
  1117.                         break;
  1118.                     case 4:
  1119.                     rrp->rdata.soa->minimum = value;
  1120.                         break;
  1121.                     }
  1122.                 }
  1123.             data = strtok(NULLCHAR,delim);
  1124.             }
  1125.         } else {
  1126.             rrp->rdata.soa->serial = atol(data);
  1127.             data = strtok(NULLCHAR,delim);
  1128.             rrp->rdata.soa->refresh = atol(data);
  1129.             data = strtok(NULLCHAR,delim);
  1130.             rrp->rdata.soa->retry = atol(data);
  1131.             data = strtok(NULLCHAR,delim);
  1132.             rrp->rdata.soa->expire = atol(data);
  1133.             data = strtok(NULLCHAR,delim);
  1134.             rrp->rdata.soa->minimum = atol(data);
  1135.         }
  1136.         rrp->rdlength += 20;
  1137.         break;
  1138.     }
  1139.     return rrp;
  1140. }
  1141.  
  1142. /* Print a resource record */
  1143. #ifndef ENH
  1144. static
  1145. #endif
  1146. void
  1147. put_rr(fp,rrp,addorg)
  1148. FILE *fp;
  1149. struct rr *rrp;
  1150. int addorg;
  1151. {
  1152.     if(fp == NULLFILE || rrp == NULLRR)
  1153.         return;
  1154.  
  1155.     fputs(rrp->name,fp);
  1156.  
  1157.     if(addorg) {
  1158.         if(rrp->name[strlen(rrp->name)-1] != '.' && rrp->origin != NULLCHAR){
  1159.             fprintf(fp,".%s",rrp->origin);
  1160.         }
  1161.     }
  1162.     if(rrp->ttl){
  1163.         fprintf(fp,"\t%lu",rrp->ttl);
  1164.     }
  1165.     if(rrp->class == CLASS_IN){
  1166.         fputs("\tIN",fp);
  1167.     } else {
  1168.         if(rrp->ttl == 0)
  1169.             fprintf(fp,"\t%lu",rrp->ttl);
  1170.         fprintf(fp,"\t%u",rrp->class);
  1171.     }
  1172.  
  1173.     if(rrp->type < NDTYPES)
  1174.         fprintf(fp,"\t%s",type2str(rrp->type));
  1175.     else
  1176.         fprintf(fp,"\t%u",rrp->type);
  1177.  
  1178.     if(rrp->rdlength != 0){
  1179.         fputc('\t',fp);
  1180.         switch(rrp->type){
  1181.         case TYPE_MINFO:    /* Unsupported type */
  1182.             fprintf(fp,"%s\t%s",
  1183.                 rrp->rdata.minfo.rmailbx,
  1184.                 rrp->rdata.minfo.emailbx);
  1185.             break;
  1186.         case TYPE_MD:        /* Unsupported type */
  1187.         case TYPE_MF:        /* Unsupported type */
  1188.         case TYPE_NULL:        /* Unsupported type */
  1189.         case TYPE_WKS:        /* Unsupported type */
  1190.             fputs(rrp->rdata.data,fp);
  1191.             break;
  1192.         case TYPE_CNAME:
  1193.         case TYPE_MB:
  1194.         case TYPE_MG:
  1195.         case TYPE_MR:
  1196.         case TYPE_NS:
  1197.         case TYPE_PTR:
  1198.         case TYPE_TXT:
  1199.             /* These are all printable text strings */
  1200.             fputs(rrp->rdata.data,fp);
  1201.             break;
  1202.         case TYPE_A:
  1203.             fprintf(fp,"%s",inet_ntoa(rrp->rdata.addr));
  1204.             break;
  1205.         case TYPE_MX:
  1206.             fprintf(fp,"%u\t%s",rrp->rdata.mx.pref,
  1207.              rrp->rdata.mx.exch);
  1208.             break;
  1209.         case TYPE_SOA:
  1210.             fprintf(fp,"%s\t%s\t%lu\t%lu\t%lu\t%lu\t%lu",
  1211.              rrp->rdata.soa->mname,rrp->rdata.soa->rname,
  1212.              rrp->rdata.soa->serial,rrp->rdata.soa->refresh,
  1213.              rrp->rdata.soa->retry,rrp->rdata.soa->expire,
  1214.              rrp->rdata.soa->minimum);
  1215.             break;
  1216.         case TYPE_HINFO:
  1217.             fprintf(fp,"%s\t%s",
  1218.              rrp->rdata.hinfo.cpu,
  1219.              rrp->rdata.hinfo.os);
  1220.             break;
  1221.         default:
  1222.             break;
  1223.         }
  1224.     }
  1225.     fputc('\n',fp);
  1226.     fflush(fp);
  1227. }
  1228.  
  1229. /* Free a domain message */
  1230. void
  1231. free_dhdr(dp)
  1232. struct dhdr *dp;
  1233. {
  1234.     int i;
  1235.  
  1236.     if(dp->qdcount){
  1237.         for(i = 0; i < dp->qdcount; i++){
  1238.             xfree(dp->qlist[i]->qname);
  1239.             xfree((char *)dp->qlist[i]);
  1240.         }
  1241.         xfree((char *)dp->qlist);
  1242.     }
  1243.     if(dp->ancount){
  1244.         for(i = 0; i < dp->ancount; i++)
  1245.             free_rr(dp->ans[i]);
  1246.         xfree((char *)dp->ans);
  1247.     }
  1248.     if(dp->nscount){
  1249.         for(i = 0; i < dp->nscount; i++)
  1250.             free_rr(dp->ns[i]);
  1251.         xfree((char *)dp->ns);
  1252.     }
  1253.     if(dp->arcount){
  1254.         for(i = 0; i < dp->arcount; i++)
  1255.             free_rr(dp->add[i]);
  1256.         xfree((char *)dp->add);
  1257.     }
  1258.     xfree((char *)dp);
  1259. }
  1260.  
  1261. int
  1262. ntohdomain(struct dhdr *dhdr,struct mbuf **bpp)
  1263. {
  1264.    int i;
  1265.       int16 tmp, len = len_p(*bpp);
  1266.          char *cp,*msg;
  1267.          
  1268.             /* packet size must be greater then header size */
  1269.                if(len < 12)
  1270.                     return -1;
  1271.                     
  1272.                        msg = mxallocw(len);
  1273.                           pullup(bpp,msg,len);
  1274.                              memset((char *)dhdr,0,sizeof(*dhdr));
  1275.  
  1276.  
  1277.     dhdr->id = get16(&msg[0]);
  1278.     tmp = get16(&msg[2]);
  1279.     if(tmp & DOM_RESPONSE)
  1280.         dhdr->qr = 1;
  1281.     dhdr->opcode = (tmp >> 11) & 0xf;
  1282.     if(tmp & DOM_AUTHORITY)
  1283.         dhdr->aa = 1;
  1284.     if(tmp & DOM_TRUNC)
  1285.         dhdr->tc = 1;
  1286.     if(tmp & DOM_DORECURSE)
  1287.         dhdr->rd = 1;
  1288.     if(tmp & DOM_CANRECURSE)
  1289.         dhdr->ra = 1;
  1290.     dhdr->rcode = tmp & 0xf;
  1291.     dhdr->qdcount = get16(&msg[4]);
  1292.     dhdr->ancount = get16(&msg[6]);
  1293.     dhdr->nscount = get16(&msg[8]);
  1294.     dhdr->arcount = get16(&msg[10]);
  1295.  
  1296.     /* Now parse the variable length sections */
  1297.     cp = &msg[12];
  1298.  
  1299.     /* Question section */
  1300.     if(dhdr->qdcount != 0)
  1301.         dhdr->qlist = (struct quest **)cxallocw(dhdr->qdcount,sizeof(struct quest *));
  1302.     for(i=0;i<dhdr->qdcount;i++){
  1303.         dhdr->qlist[i] = (struct quest *)mxallocw(sizeof(struct quest));
  1304.         if((cp = getq(dhdr->qlist[i],msg,cp)) == NULLCHAR)
  1305.             goto quit;
  1306.     }
  1307.     /* Answer section */
  1308.     if(dhdr->ancount != 0)
  1309.         dhdr->ans = (struct rr **)cxallocw(dhdr->ancount,sizeof(struct rr *));
  1310.     for(i=0;i<dhdr->ancount;i++){
  1311.         dhdr->ans[i] = (struct rr *)mxallocw(sizeof(struct rr));
  1312.         if((cp = ntohrr(dhdr->ans[i],msg,cp)) == NULLCHAR)
  1313.             goto quit;
  1314.     }
  1315.     /* Name server (authority) section */
  1316.     if(dhdr->nscount != 0)
  1317.         dhdr->ns = (struct rr **)cxallocw(dhdr->nscount,sizeof(struct rr *));
  1318.     for(i=0;i<dhdr->nscount;i++){
  1319.         dhdr->ns[i] = (struct rr *)mxallocw(sizeof(struct rr));
  1320.         if((cp = ntohrr(dhdr->ns[i],msg,cp)) == NULLCHAR)
  1321.             goto quit;
  1322.     }
  1323.     /* Additional section */
  1324.     if(dhdr->arcount != 0)
  1325.         dhdr->add = (struct rr **)cxallocw(dhdr->arcount,sizeof(struct rr *));
  1326.     for(i=0;i<dhdr->arcount;i++){
  1327.         dhdr->add[i] = (struct rr *)mxallocw(sizeof(struct rr));
  1328.         if((cp = ntohrr(dhdr->add[i],msg,cp)) == NULLCHAR)
  1329.             goto quit;
  1330.     }
  1331. quit:
  1332.     xfree(msg);
  1333.     return 0;
  1334. }
  1335.  
  1336. void
  1337. proc_answer(dhdr,dp,dfp)
  1338. struct dhdr *dhdr;
  1339. struct dserver *dp;
  1340. FILE *dfp;
  1341. {
  1342.     FILE *fp;
  1343.     int i;
  1344.     int32 rtt,abserr;
  1345.     long ttl = 500;    /* Default TTL for negative records without SOA */
  1346.     struct rr *rrp;
  1347.     struct quest *qp;
  1348.  
  1349.     /* Compute and update the round trip time if its a domain server */
  1350.     if(dp != NULLDOM) {
  1351.         rtt = ((secclock() - (int32)dhdr->id)) * 1000;
  1352.         abserr = rtt > dp->srtt ? rtt - dp->srtt : dp->srtt - rtt;
  1353.         dp->srtt = ((AGAIN-1) * dp->srtt + rtt + (AGAIN/2)) >> LAGAIN;
  1354.         dp->mdev = ((DGAIN-1) * dp->mdev + abserr + (DGAIN/2)) >> LDGAIN;
  1355.         dp->timeout = 4 * dp->mdev + dp->srtt;
  1356.     }
  1357.  
  1358.     if(DBloaded == 1 && dfp == NULLFILE)
  1359.         fp = NULLFILE;    /* append to memory */
  1360.     else {
  1361.         if(dfp == NULLFILE) {
  1362.             if((fp = open_file(Dfile,APPEND_TEXT,0,1)) == NULLFILE) {
  1363.                 return;
  1364.             }
  1365.         } else {
  1366.             fp = dfp;
  1367.         }
  1368.     }
  1369.     if(dhdr->aa && (dhdr->rcode == NAME_ERROR || dhdr->ancount == 0)){
  1370.         /* Add negative reply to file. This assumes that there was
  1371.          * only one question, which is true for all questions we send.
  1372.          */
  1373.         qp = dhdr->qlist[0];
  1374.         rrp = (struct rr *)mxallocw(sizeof(struct rr));
  1375.         rrp->name = strxdup(qp->qname);
  1376.         rrp->type = qp->qtype;
  1377.         rrp->class = qp->qclass;
  1378.         rrp->ttl = ttl;
  1379.         rrp->rdlength = 0;    /* no data */
  1380.         if(rrp->type == TYPE_A){
  1381.             if(add_rr(fp,rrp))
  1382.                 free_rr(rrp);    /* was already there */
  1383.         }
  1384.     }
  1385.     if(dhdr->rcode == NO_ERROR) {
  1386.         for(i=0;i< dhdr->ancount;i++){
  1387.             rrp = copy_rr(dhdr->ans[i]);
  1388.             if(rrp->type == TYPE_SOA)
  1389.                 ttl = rrp->ttl;
  1390.             if(add_rr(fp,rrp))
  1391.                 free_rr(rrp);
  1392.         }
  1393.         for(i=0;i< dhdr->nscount;i++){
  1394.             rrp = copy_rr(dhdr->ns[i]);
  1395.             if(rrp->type == TYPE_SOA)
  1396.                 ttl = rrp->ttl;
  1397.             if(add_rr(fp,rrp))
  1398.                 free_rr(rrp);
  1399.         }
  1400.         for(i=0;i< dhdr->arcount;i++){
  1401.             rrp = copy_rr(dhdr->add[i]);
  1402.             if(rrp->type == TYPE_SOA)
  1403.                 ttl = rrp->ttl;
  1404.             if(add_rr(fp,rrp))
  1405.                 free_rr(rrp);
  1406.         }
  1407.     }
  1408.     if(fp != NULLFILE && dfp == NULLFILE)
  1409.         fclose(fp);
  1410. }
  1411.  
  1412. char *
  1413. type2str(type)
  1414. int type;
  1415. {
  1416.     char *Dtypes[] = {
  1417.         "",    "A", "NS", "MD", "MF", "CNAME", "SOA", "MB", "MG",
  1418.         "MR", "NULL", "WKS", "PTR", "HINFO", "MINFO", "MX", "TXT"
  1419.     };
  1420.  
  1421.     if(type < NDTYPES)
  1422.         return Dtypes[type];
  1423.     else
  1424.         switch (type) {
  1425.             case TYPE_AXFR:
  1426.                 return "AXFR";
  1427.             case TYPE_MAILB:
  1428.                 return "MAILB";
  1429.             case TYPE_MAILA:
  1430.                 return "MAILA";
  1431.             case TYPE_ANY:
  1432.                 return "ANY";
  1433.         }
  1434.     return "UNKNOWN";
  1435. }
  1436.  
  1437. /* Return 1 if string appears to be an IP address in dotted decimal;
  1438.  * return 0 otherwise (i.e., if string is a domain name)
  1439.  */
  1440. int
  1441. isaddr(char *s)
  1442. {
  1443.     char c;
  1444.  
  1445.     if(s != NULLCHAR) {
  1446.         while((c = *s++) != '\0'){
  1447.             if(c != '[' && c != '[' && !isdigit(c) && c != '.')
  1448.                 return 0;
  1449.         }
  1450.     }
  1451.     return 1;
  1452. }
  1453.  
  1454. struct dhdr *
  1455. bld_dhdr(qr,op,flags,rcode,name,class,type)
  1456. int16 qr;
  1457. int16 op;
  1458. int16 flags;
  1459. int16 rcode;
  1460. char *name;
  1461. int class;
  1462. int type;
  1463. {
  1464.     struct dhdr *dhdr = (struct dhdr *)mxallocw(sizeof(struct dhdr));
  1465.  
  1466.     dhdr->qr = qr;
  1467.     dhdr->opcode = op;
  1468.     if(flags & DOM_AUTHORITY)
  1469.         dhdr->aa = 1;
  1470.     if(flags & DOM_TRUNC)
  1471.         dhdr->tc = 1;
  1472.     if(flags & DOM_DORECURSE)
  1473.         dhdr->rd = 1;
  1474.     if(flags & DOM_CANRECURSE)
  1475.         dhdr->ra = 1;
  1476.     dhdr->rcode = rcode;
  1477.     dhdr->id = (int16)secclock();
  1478.     dhdr->qdcount = 1;
  1479.     dhdr->qlist = (struct quest **)cxallocw(dhdr->qdcount,sizeof(struct quest *));
  1480.     dhdr->qlist[0] = (struct quest *)mxallocw(sizeof(struct quest));
  1481.     dhdr->qlist[0]->qname = strxdup(name);
  1482.     dhdr->qlist[0]->qtype = type;
  1483.     dhdr->qlist[0]->qclass = class;
  1484.     return dhdr;
  1485. }
  1486.  
  1487. int
  1488. res_mkbuf(dhdr,buffer,buflen)
  1489. struct dhdr *dhdr;
  1490. char *buffer;    /* Area for query */
  1491. int16 buflen;    /* Length of same */
  1492. {
  1493.     int16 parameter;
  1494.     int i, count;
  1495.     char *cp = buffer;
  1496.  
  1497.     cp = put16(cp,dhdr->id);
  1498.     parameter = (dhdr->qr) ? 0x8000 : 0;
  1499.     parameter |= ((dhdr->opcode & 0x0f) << 11);
  1500.     if(dhdr->aa)
  1501.         parameter |= DOM_AUTHORITY;
  1502.     if(dhdr->tc)
  1503.         parameter |= DOM_TRUNC;
  1504.     if(dhdr->rd)
  1505.         parameter |= DOM_DORECURSE;
  1506.     if(dhdr->ra)
  1507.         parameter |= DOM_CANRECURSE;
  1508.     parameter |= (dhdr->rcode & 0x0f);
  1509.     cp = put16(cp,parameter);
  1510.     cp = put16(cp,dhdr->qdcount);
  1511.     cp = put16(cp,dhdr->ancount);
  1512.     cp = put16(cp,dhdr->nscount);
  1513.     cp = put16(cp,dhdr->arcount);
  1514.     if((count = dhdr->qdcount) > 0) {
  1515.         for(i = 0; i < count; i++) {
  1516.             cp = dn_compress(cp,dhdr->qlist[i]->qname);
  1517.             cp = put16(cp,dhdr->qlist[i]->qtype);
  1518.             cp = put16(cp,dhdr->qlist[i]->qclass);
  1519.         }
  1520.     }
  1521.     if((count = dhdr->ancount) > 0)
  1522.         for(i = 0; i < count; i++) {
  1523.             cp = htonrr(dhdr->ans[i],cp);
  1524.         }
  1525.     if((count = dhdr->nscount) > 0)
  1526.         for(i = 0; i < count; i++) {
  1527.             cp = htonrr(dhdr->ns[i],cp);
  1528.         }
  1529.     if((count = dhdr->arcount) > 0)
  1530.         for(i = 0; i < count; i++) {
  1531.             cp = htonrr(dhdr->add[i],cp);
  1532.         }
  1533.     return (int)(cp - buffer);
  1534. }
  1535.  
  1536.